/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package be.ugent.medirem.persistence.facade;

import be.ugent.medirem.persistence.entity.MedicationTask;
import be.ugent.medirem.persistence.entity.Patient;
import be.ugent.medirem.persistence.entity.Prescription;
import be.ugent.medirem.persistence.entity.details.MedicationTaskDetails;
import be.ugent.medirem.persistence.entity.values.MedicationTaskValues;
import be.ugent.medirem.persistence.exception.EntityNotFoundException;
import be.ugent.medirem.persistence.util.EntityDetailsToEntity;
import be.ugent.medirem.persistence.util.TaskStatus;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

/**
 *
 * @author Thomas Roelens
 */
@Stateless
public class MedicationTaskDaoBean implements MedicationTaskDaoLocal {

    @PersistenceContext
    private EntityManager em;

    public Long create(MedicationTaskValues details) throws IllegalArgumentException {
        if (details.getPrescriptionId() == null) {
            throw new IllegalArgumentException("Prescription id is null");
        }
        if (details.getTaskTime() == null) {
            throw new IllegalArgumentException("Task time is null");
        }

        Prescription pre = null;

        try {
            pre = em.find(Prescription.class, details.getPrescriptionId());
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        MedicationTask task = new MedicationTask(pre, details.getTaskTime());
        create(task);

        // Add the task to the prescription
        pre.addTask(task);
        em.merge(pre);

        return task.getId();
    }

    public void remove(Long taskId) throws IllegalArgumentException, EntityNotFoundException {
        if (taskId == null) {
            throw new IllegalArgumentException("Task id is null");
        }
        MedicationTask task = em.find(MedicationTask.class, taskId);
        if (task == null) {
            throw new EntityNotFoundException("Task not found with id " + taskId);
        }

        // Remove the task from the prescription tasklist
        Prescription prescription = task.getPrescription();
        if (prescription.getTasks().contains(task)) {
            prescription.removeTask(task);
        }

        remove(task);
    }

    public void update(Long taskId, MedicationTaskValues details) throws IllegalArgumentException, EntityNotFoundException {
        if (taskId == null) {
            throw new IllegalArgumentException("Task id is null");
        }
        MedicationTask task = em.find(MedicationTask.class, taskId);
        if (task == null) {
            throw new EntityNotFoundException("Task not found with id " + taskId);
        }

        if (details.getTaskTime() != null) {
            task.setTaskTime(details.getTaskTime());
        }
        if (details.getCompletionTime() != null) {
            task.setCompletionTime(details.getCompletionTime());
        }
        TaskStatus status = details.getStatus();
        if (status != null) {

            task.setStatus(status);
        } else {
            throw new IllegalArgumentException("Task status invalid");
        }

        edit(task);
    }

    public void updateStatus(Long taskId, TaskStatus status) throws IllegalArgumentException, EntityNotFoundException {
        if (taskId == null) {
            throw new IllegalArgumentException("Task id is null");
        }

        MedicationTask task = em.find(MedicationTask.class, taskId);

        if (task == null) {
            throw new EntityNotFoundException("Task not found with id " + taskId);
        }

        task.setStatus(status);

        edit(task);
    }

    public MedicationTaskDetails getDetails(
            Long taskId) throws IllegalArgumentException, EntityNotFoundException {
        if (taskId == null) {
            throw new IllegalArgumentException("Task id is null");
        }

        MedicationTask task = em.find(MedicationTask.class, taskId);

        if (task == null) {
            throw new EntityNotFoundException("Task not found with id " + taskId);
        }
        return convert(task);
    }

    public List<String> getAllTaskStatus() {
        List<String> statusList = new ArrayList<String>();

        for (TaskStatus ts : TaskStatus.values()) {
            statusList.add(ts.getTitle());
        }

        return statusList;
    }

    public List<MedicationTaskDetails> getAllTasks(Long patientId) throws IllegalArgumentException, EntityNotFoundException {
        List<MedicationTaskDetails> taskList = new ArrayList<MedicationTaskDetails>();
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }

        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                for (Prescription p : patient.getPrescriptions()) {
                    for (MedicationTask t : p.getTasks()) {
                        taskList.add(convert(t));
                    }
                }
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return taskList;
    }

    public List<MedicationTaskDetails> getTasks(Long patientId, TaskStatus status) throws IllegalArgumentException, EntityNotFoundException {
        List<MedicationTaskDetails> taskList = new ArrayList<MedicationTaskDetails>();
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }

        try {
            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            } else {
                for (Prescription p : patient.getPrescriptions()) {
                    for (MedicationTask t : p.getTasks()) {
                        if (t.getStatus().equals(status)) {
                            taskList.add(convert(t));
                        }
                    }
                }
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return taskList;
    }

    public void persist(Object object) {
        em.persist(object);
    }

    public void create(MedicationTask task) {
        em.persist(task);
    }

    public void edit(MedicationTask task) {
        em.merge(task);
    }

    public void remove(MedicationTask task) {
        em.remove(em.merge(task));
    }

    private MedicationTaskDetails convert(MedicationTask task) {
        if (task == null) {
            return null;
        }

        return EntityDetailsToEntity.medicationTaskToDetails(task);
    }

    public String getCompleteTaskStatus() {
        return TaskStatus.COMPLETED.getTitle();
    }

    public String getIncompleteTaskStatus() {
        return TaskStatus.NOT_COMPLETED.getTitle();
    }

    public MedicationTaskDetails getNextTask(Long patientId, Long prescriptionId) throws IllegalArgumentException, EntityNotFoundException {
        MedicationTaskDetails task = null;
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        if (prescriptionId == null) {
            throw new IllegalArgumentException("Prescription id is null");
        }

        try {
            Prescription p = em.find(Prescription.class, prescriptionId);

            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            }
            if (p == null) {
                throw new EntityNotFoundException();
            }
            if (!patient.getPrescriptions().contains(p)) {
                throw new IllegalArgumentException("Patient with given id doesn't contain prescription with given id");
            }
            for (MedicationTask t : p.getTasks())
                if (t.getStatus().equals(TaskStatus.NOT_COMPLETED) || t.getStatus().equals(TaskStatus.NOT_SEEN))
                    task = convert(t);
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return task;
    }

    public List<MedicationTaskDetails> getTasks(Long patientId, Long prescriptionId) throws IllegalArgumentException, EntityNotFoundException {
        List<MedicationTaskDetails> tasks = new ArrayList<MedicationTaskDetails>();
        Patient patient = null;

        if (patientId == null) {
            throw new IllegalArgumentException("Patient id is null");
        }
        if (prescriptionId == null) {
            throw new IllegalArgumentException("Prescription id is null");
        }

        try {
            Prescription p = em.find(Prescription.class, prescriptionId);

            patient = em.find(Patient.class, patientId);

            if (patient == null) {
                throw new EntityNotFoundException();
            }
            if (p == null) {
                throw new EntityNotFoundException();
            }
            if (!patient.getPrescriptions().contains(p)) {
                throw new IllegalArgumentException("Patient with given id doesn't contain prescription with given id");
            }
            for (MedicationTask t : p.getTasks())
                    tasks.add(convert(t));
            
        } catch (Exception ex) {
            throw new EJBException(ex);
        }

        return tasks;
    }
}
